package org.cybzacg.convert;


import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.context.impl.DefaultConversionContext;
import org.cybzacg.convert.core.AbstractTypeConverter;
import org.cybzacg.convert.core.TypeConverter;
import org.cybzacg.convert.enums.ConversionError;
import org.cybzacg.convert.enums.ConversionStrategyEnum;
import org.cybzacg.convert.exception.ConversionException;
import org.cybzacg.convert.factory.AutoConverterRegistrar;
import org.cybzacg.convert.factory.ConversionStrategyFactory;
import org.cybzacg.convert.factory.ConverterFactory;
import org.cybzacg.convert.listener.ConversionListener;
import org.cybzacg.convert.model.RegistrationStatistics;
import org.cybzacg.convert.scanner.Filter;
import org.cybzacg.convert.strategy.ConversionStrategy;
import org.cybzacg.convert.converters.PropertyCopier;
import org.cybzacg.convert.config.CopyConfig;
import org.cybzacg.convert.cache.CopyCache;

import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 类型转换引擎
 * 整合工厂模式、策略模式、观察者模式等设计模式
 *
 * @author cybzacg.blog
 * @version 3.0
 * @since 3.0
 */
@Slf4j
public class ConversionEngine {

    /**
     * 单例实例
     */
    private static final AtomicReference<ConversionEngine> instance = new AtomicReference<>();

    /**
     * 自动转换器注册器
     */
    private final AutoConverterRegistrar autoConverterRegistrar;

    /**
     * 转换监听器列表
     */
    private final List<ConversionListener> listeners = new CopyOnWriteArrayList<>();

    /**
     * 全局转换上下文
     */
    private final AtomicReference<ConversionContext> globalContext = new AtomicReference<>();

    /**
     * 属性拷贝器实例
     */
    private final AtomicReference<PropertyCopier> propertyCopier = new AtomicReference<>();

    private List<String> scanPackage = List.of("org.cybzacg.convert");

    /**
     * 添加扫描包
     * @param packageName 包扫描路径
     */
    public void addScanPackage(String ... packageName){
        scanPackage.addAll(List.of(packageName));
    }

    /**
     * 私有构造方法
     */
    private ConversionEngine() {
        log.debug("初始化ConversionEngine实例");
        this.autoConverterRegistrar = new AutoConverterRegistrar();
        this.autoConverterRegistrar.scanAndRegister(scanPackage);
        this.globalContext.set(new DefaultConversionContext());
        this.propertyCopier.set(new PropertyCopier());
        log.info("ConversionEngine初始化完成");
    }

    /**
     * 获取引擎实例
     *
     * @return 引擎实例
     */
    public static ConversionEngine getInstance() {
        ConversionEngine current = instance.get();
        if (current == null) {
            synchronized (ConversionEngine.class) {
                current = instance.get();
                if (current == null) {
                    current = new ConversionEngine();
                    instance.set(current);
                }
            }
        }
        return current;
    }

    /**
     * 执行类型转换
     *
     * @param <T> 目标类型
     * @param source 源对象
     * @param targetType 目标类型
     * @return 转换结果
     * @throws ConversionException 转换失败时抛出
     */
    public <T> T convert(Object source, Class<T> targetType) throws ConversionException {
        return convert(source, targetType, null);
    }

    /**
     * 执行类型转换
     *
     * @param <T> 目标类型
     * @param source 源对象
     * @param targetType 目标类型
     * @param defaultValue 默认值
     * @return 转换结果
     * @throws ConversionException 转换失败时抛出
     */
    public <T> T convert(Object source, Class<T> targetType, T defaultValue) throws ConversionException {
        return convert(source, targetType, defaultValue, globalContext.get());
    }

    /**
     * 执行类型转换（带上下文）
     *
     * @param <T> 目标类型
     * @param source 源对象
     * @param targetType 目标类型
     * @param defaultValue 默认值
     * @param context 转换上下文
     * @return 转换结果
     * @throws ConversionException 转换失败时抛出
     */
    public <T> T convert(Object source, Class<T> targetType, T defaultValue, ConversionContext context)
            throws ConversionException {

        if (context == null) {
            context = globalContext.get();
        }

        // 创建转换上下文副本以避免并发问题
        ConversionContext conversionContext = context.copy();
        conversionContext.setSourceType(source != null ? source.getClass() : null);
        conversionContext.setTargetType(targetType);
        conversionContext.setDefaultValue(defaultValue);

        // 通知转换开始
        notifyConversionStart(conversionContext, source);

        try {
            // 获取转换器
            TypeConverter converter = autoConverterRegistrar.getConverterFactory().getConverter(targetType);

            // 添加全局监听器到转换器（仅当转换器是AbstractTypeConverter的实例时）
            if (converter instanceof AbstractTypeConverter abstractConverter) {
                listeners.forEach(abstractConverter::addListener);
            }

            // 获取转换策略
            ConversionStrategy strategy = ConversionStrategyFactory.getStrategy(conversionContext);

            // 使用策略执行转换
            T result = strategy.execute(converter, source, targetType, defaultValue, conversionContext);

            // 通知转换成功
            notifyConversionSuccess(conversionContext, source, result);

            return result;

        } catch (Exception e) {
            // 通知转换失败
            notifyConversionFailure(conversionContext, source, e);

            if (e instanceof ConversionException ex) {
                throw ex;
            }

            throw new ConversionException(
                ConversionError.CONVERSION_FAILED,
                "转换失败: " + e.getMessage(), e);
        }
    }

    /**
     * 检查是否支持指定类型的转换
     *
     * @param targetType 目标类型
     * @return 是否支持
     */
    public boolean supports(Class<?> targetType) {
        return autoConverterRegistrar.getConverterFactory().supports(targetType);
    }

    /**
     * 获取支持的类型列表
     *
     * @return 支持的类型列表
     */
    public Set<Class<?>> getSupportedTypes() {
        return autoConverterRegistrar.getConverterFactory().getSupportedTypes();
    }

    /**
     * 注册转换器
     *
     * @param converter 转换器
     */
    public void registerConverter(TypeConverter converter) {
        log.debug("注册转换器: {}", converter.getName());
        autoConverterRegistrar.getConverterFactory().registerConverter(converter);
        log.info("转换器注册成功: {}", converter.getName());
    }

    /**
     * 移除转换器
     *
     * @param converterName 转换器名称
     * @return 是否成功移除
     */
    public boolean removeConverter(String converterName) {
        return autoConverterRegistrar.getConverterFactory().removeConverter(converterName);
    }

    /**
     * 启用转换器
     *
     * @param converterName 转换器名称
     * @return 是否成功启用
     */
    public boolean enableConverter(String converterName) {
        return autoConverterRegistrar.getConverterFactory().enableConverter(converterName);
    }

    /**
     * 禁用转换器
     *
     * @param converterName 转换器名称
     * @return 是否成功禁用
     */
    public boolean disableConverter(String converterName) {
        return autoConverterRegistrar.getConverterFactory().disableConverter(converterName);
    }

    /**
     * 添加监听器
     *
     * @param listener 监听器
     */
    public void addListener(ConversionListener listener) {
        if (listener != null && listener.isEnabled()) {
            listeners.add(listener);
        }
    }

    /**
     * 移除监听器
     *
     * @param listener 监听器
     */
    public void removeListener(ConversionListener listener) {
        listeners.remove(listener);
    }

    /**
     * 清除所有监听器
     */
    public void clearListeners() {
        listeners.clear();
    }

    /**
     * 设置全局转换上下文
     *
     * @param context 转换上下文
     */
    public void setGlobalContext(ConversionContext context) {
        this.globalContext.set(context != null ? context : new DefaultConversionContext());
    }

    /**
     * 获取全局转换上下文
     *
     * @return 转换上下文
     */
    public ConversionContext getGlobalContext() {
        return globalContext.get();
    }

    /**
     * 获取转换器工厂统计信息
     *
     * @return 统计信息
     */
    public ConverterFactory.FactoryStatistics getStatistics() {
        return autoConverterRegistrar.getConverterFactory().getStatistics();
    }

    /**
     * 获取策略工厂统计信息
     *
     * @return 策略统计信息
     */
    public ConversionStrategyFactory.StrategyStatistics getStrategyStatistics() {
        return ConversionStrategyFactory.getStatistics();
    }

    /**
     * 注册自定义转换策略
     *
     * @param strategy 策略枚举
     * @param strategyInstance 策略实例
     */
    public void registerStrategy(ConversionStrategyEnum strategy,
                                 ConversionStrategy strategyInstance) {
        ConversionStrategyFactory.registerStrategy(strategy, strategyInstance);
    }

    /**
     * 移除转换策略
     *
     * @param strategy 策略枚举
     * @return 是否成功移除
     */
    public boolean removeStrategy(ConversionStrategyEnum strategy) {
        return ConversionStrategyFactory.removeStrategy(strategy);
    }

    /**
     * 检查策略是否存在
     *
     * @param strategy 策略枚举
     * @return 是否存在
     */
    public boolean hasStrategy(ConversionStrategyEnum strategy) {
        return ConversionStrategyFactory.hasStrategy(strategy);
    }

    /**
     * 获取所有可用的策略
     *
     * @return 策略枚举数组
     */
    public ConversionStrategyEnum[] getAvailableStrategies() {
        return ConversionStrategyFactory.getAvailableStrategies();
    }

    /**
     * 自动扫描并注册转换器
     *
     * @param packageName 要扫描的包名
     * @return 注册统计信息
     */
    public RegistrationStatistics autoRegister(String packageName) {
        return autoConverterRegistrar.scanAndRegister(packageName);
    }

    /**
     * 自动扫描并注册转换器
     *
     * @param packageNames 要扫描的包名列表
     * @return 注册统计信息
     */
    public RegistrationStatistics autoRegister(List<String> packageNames) {
        return autoConverterRegistrar.scanAndRegister(packageNames);
    }

    /**
     * 自动扫描并注册转换器（带过滤器）
     *
     * @param packageName 要扫描的包名
     * @param filter 过滤器
     * @return 注册统计信息
     */
    public RegistrationStatistics autoRegister(String packageName, Filter filter) {
        return autoConverterRegistrar.scanAndRegister(packageName, filter);
    }

    /**
     * 自动扫描并注册转换器（带过滤器）
     *
     * @param packageNames 要扫描的包名列表
     * @param filter 过滤器
     * @return 注册统计信息
     */
    public RegistrationStatistics autoRegister(List<String> packageNames, Filter filter) {
        return autoConverterRegistrar.scanAndRegister(packageNames, filter);
    }

    // ==================== PropertyCopier 集成方法 ====================

    /**
     * 获取属性拷贝器实例
     * 
     * @return 属性拷贝器实例
     */
    public PropertyCopier getPropertyCopier() {
        PropertyCopier copier = propertyCopier.get();
        if (copier == null) {
            synchronized (propertyCopier) {
                copier = propertyCopier.get();
                if (copier == null) {
                    copier = new PropertyCopier();
                    propertyCopier.set(copier);
                }
            }
        }
        return copier;
    }

    /**
     * 创建属性拷贝器
     * 
     * @param config 拷贝配置
     * @return 属性拷贝器实例
     */
    public PropertyCopier createPropertyCopier(CopyConfig config) {
        return new PropertyCopier(config);
    }

    /**
     * 属性拷贝方法
     * 
     * @param <T> 目标类型
     * @param source 源对象
     * @param targetType 目标类型
     * @return 拷贝后的对象
     */
    public <T> T copyProperties(Object source, Class<T> targetType) {
        return getPropertyCopier().copy(source, targetType);
    }

    /**
     * 带配置的属性拷贝方法
     * 
     * @param <T> 目标类型
     * @param source 源对象
     * @param targetType 目标类型
     * @param config 拷贝配置
     * @return 拷贝后的对象
     */
    public <T> T copyProperties(Object source, Class<T> targetType, CopyConfig config) {
        return getPropertyCopier().copy(source, targetType, config);
    }

    /**
     * 对象间属性拷贝
     * 
     * @param source 源对象
     * @param target 目标对象
     */
    public void copyProperties(Object source, Object target) {
        getPropertyCopier().copyProperties(source, target);
    }

    /**
     * 带配置的对象间属性拷贝
     * 
     * @param source 源对象
     * @param target 目标对象
     * @param config 拷贝配置
     */
    public void copyProperties(Object source, Object target, CopyConfig config) {
        getPropertyCopier().copyProperties(source, target, config);
    }

    /**
     * 浅拷贝
     * 
     * @param <T> 目标类型
     * @param source 源对象
     * @param targetType 目标类型
     * @return 浅拷贝结果
     */
    public <T> T shallowCopy(Object source, Class<T> targetType) {
        return getPropertyCopier().shallowCopy(source, targetType);
    }

    /**
     * 深拷贝
     * 
     * @param <T> 目标类型
     * @param source 源对象
     * @param targetType 目标类型
     * @return 深拷贝结果
     */
    public <T> T deepCopy(Object source, Class<T> targetType) {
        return getPropertyCopier().deepCopy(source, targetType);
    }

    /**
     * 克隆拷贝
     * 
     * @param <T> 目标类型
     * @param source 源对象
     * @return 克隆结果
     */
    @SuppressWarnings("unchecked")
    public <T> T cloneCopy(T source) {
        return getPropertyCopier().cloneCopy(source);
    }

    /**
     * 批量拷贝
     * 
     * @param <T> 目标类型
     * @param sources 源对象列表
     * @param targetType 目标类型
     * @return 拷贝结果列表
     */
    public <T> List<T> batchCopy(List<?> sources, Class<T> targetType) {
        return getPropertyCopier().batchCopy(sources, targetType);
    }

    /**
     * 带配置的批量拷贝
     * 
     * @param <T> 目标类型
     * @param sources 源对象列表
     * @param targetType 目标类型
     * @param config 拷贝配置
     * @return 拷贝结果列表
     */
    public <T> List<T> batchCopy(List<?> sources, Class<T> targetType, CopyConfig config) {
        return getPropertyCopier().batchCopy(sources, targetType, config);
    }

    /**
     * 获取属性拷贝缓存统计信息
     * 
     * @return 缓存统计信息
     */
    public CopyCache.CacheStatistics getPropertyCopyCacheStatistics() {
        return getPropertyCopier().getCacheStatistics();
    }

    /**
     * 清除属性拷贝缓存
     */
    public void clearPropertyCopyCache() {
        getPropertyCopier().clearCache();
    }

    /**
     * 获取自动注册器实例
     *
     * @return 自动注册器
     */
    public AutoConverterRegistrar getAutoRegistrar() {
        return autoConverterRegistrar;
    }

    /**
     * 重置引擎
     */
    public void reset() {
        autoConverterRegistrar.rescanAndRegister(scanPackage);
        listeners.clear();
        globalContext.set(new DefaultConversionContext());
        
        // 重置属性拷贝器
        PropertyCopier copier = propertyCopier.get();
        if (copier != null) {
            copier.clearCache();
        }
        propertyCopier.set(new PropertyCopier());
    }

    /**
     * 通知转换开始
     */
    private void notifyConversionStart(ConversionContext context, Object source) {
        for (ConversionListener listener : listeners) {
            try {
                listener.onConversionStart(context, source);
            } catch (Exception e) {
                // 监听器异常不影响转换过程
            }
        }
    }

    /**
     * 通知转换成功
     */
    private void notifyConversionSuccess(ConversionContext context, Object source, Object result) {
        for (ConversionListener listener : listeners) {
            try {
                listener.onConversionSuccess(context, source, result);
            } catch (Exception e) {
                // 监听器异常不影响转换过程
            }
        }
    }

    /**
     * 通知转换失败
     */
    private void notifyConversionFailure(ConversionContext context, Object source, Exception exception) {
        for (ConversionListener listener : listeners) {
            try {
                listener.onConversionFailure(context, source, exception);
            } catch (Exception e) {
                // 监听器异常不影响转换过程
            }
        }
    }

    /**
     * 建造者类
     */
    public static class Builder {
        private final ConversionEngine engine;

        public Builder() {
            this.engine = new ConversionEngine();
        }

        public Builder addConverter(TypeConverter converter) {
            engine.registerConverter(converter);
            return this;
        }

        public Builder addListener(ConversionListener listener) {
            engine.addListener(listener);
            return this;
        }

        public Builder setGlobalContext(ConversionContext context) {
            engine.setGlobalContext(context);
            return this;
        }

        public Builder setStrategy(ConversionStrategyEnum strategy) {
            engine.globalContext.get().setStrategy(strategy);
            return this;
        }

        public Builder enableCache(boolean enabled) {
            engine.globalContext.get().setCacheEnabled(enabled);
            return this;
        }

        public Builder enableValidation(boolean enabled) {
            engine.globalContext.get().setValidationEnabled(enabled);
            return this;
        }

        public Builder setMaxDepth(int maxDepth) {
            engine.globalContext.get().setDepth(maxDepth);
            return this;
        }

        public ConversionEngine build() {
            return engine;
        }
    }

    /**
     * 创建建造者实例
     *
     * @return 建造者实例
     */
    public static Builder builder() {
        return new Builder();
    }

    @Override
    public String toString() {
        return String.format("ConversionEngine{统计信息=%s, 监听器数量=%d, 属性拷贝器=%s}",
                           getStatistics(), listeners.size(), 
                           propertyCopier.get() != null ? "已初始化" : "未初始化");
    }
}
